using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Xml;

namespace XmlObjects.XmlDocumentMarkup
{
	public abstract class DocumentPropertyReader : IXmlDocumentPropertyReader
	{
		protected PropertyInfo propertyInfo;


		public static bool IsDecorated(PropertyInfo propertyInfo)
		{
			object[] customAttributes = propertyInfo.GetCustomAttributes(false);
			return IncludesDecoration(customAttributes);
		}

		public abstract void WriteXml(XmlNode node, DocumentElement theObject, XmlDocument ownerDocument);
		public abstract void ReadXml(XmlNode node, object theObject);

		public static bool IsXmlElement(Type type)
		{
			return IncludesDecoration(type.GetCustomAttributes(typeof(XmlElementAttribute), false));
		}


		private static bool IncludesDecoration(object[] customAttributes)
		{
			foreach (object o in customAttributes)
			{
				if (o is XmlMarkupAttribute)
					return true;
			}
			return false;
		}

		public static IList<IXmlDocumentPropertyReader> GetPropertyReaders(object theObject)
		{
			List<IXmlDocumentPropertyReader> readers = new List<IXmlDocumentPropertyReader>();
			foreach (PropertyInfo propertyInfo in theObject.GetType().GetProperties())
			{
				if (IsDecorated(propertyInfo))
				{
					IXmlDocumentPropertyReader reader = GetReader(propertyInfo);
//					IXmlDocumentPropertyReader reader = XmlObjectHydrator.GetReader(propertyInfo.PropertyType);
					if (reader != null)
						readers.Add(reader);
				}
			}
			return readers;
		}

		public static IXmlDocumentPropertyReader GetReader(PropertyInfo propertyInfo)
		{
			if (AttributePropertyReader.IsMyType(propertyInfo))
				return new AttributePropertyReader(propertyInfo);
			else if (BasicXmlElementPropertyReader.IsMyType(propertyInfo))
				return new BasicXmlElementPropertyReader(propertyInfo);
			else
				return new ElementPropertyReader(propertyInfo);
		}

		protected static T GetAttribute<T>(PropertyInfo propertyInfo) where T : Attribute
		{
			object[] objects = propertyInfo.GetCustomAttributes(typeof(T), true);
			if (objects != null && objects.Length > 0)
				return (T)objects[0];
			else
				return null;
		}

		protected DocumentPropertyReader()
		{
		}

		public DocumentPropertyReader(PropertyInfo info)
		{
			propertyInfo = info;

		}
	}

}
